import numpy as np
import math
from scipy.misc import derivative

class NonLinear:
    def __init__(self, funcs):
        # 初始化函数列表
        self.funcs = funcs

    def fn(self, x):
        # 返回第一个函数的值
        return self.funcs[0](x)

    def Fn(self, x):
        # 返回所有函数值的数组
        return np.array([self.funcs[i](x) for i in range(len(self.funcs))])

    def fixed_iter(self, x0, delta):
        # 不动点迭代法
        x = x0
        next_x = x0
        count = 0
        while True:
            next_x = self.fn(x)  # 计算下一个迭代值
            err = abs(x - next_x)  # 计算误差
            if err < delta:  # 当误差小于设定的阈值时停止迭代
                break
            else:
                x = next_x  # 更新当前值
            count += 1  # 迭代次数加1
        return (next_x, count)  # 返回结果和迭代次数
    
    def stefenson_iter(self, x0, delta):
        # 斯蒂芬森加速迭代法
        x = x0
        y = x0
        z = x0
        next_x = x0
        count = 0
        while True:
            y = self.fn(x)  # 计算f(x)
            z = self.fn(y)  # 计算f(f(x))
            # 计算加速迭代公式
            next_x = x - ((y - x)*(y - x) / (z - 2*y +x))
            err = abs(next_x - x)  # 计算误差
            if err < delta:  # 当误差小于设定的阈值时停止迭代
                break
            else:
                x = next_x  # 更新当前值
            count += 1  # 迭代次数加1
        return (next_x, count)  # 返回结果和迭代次数

    def newton_iter(self, x0, delta):
        # 牛顿迭代法
        x = x0
        next_x = x0
        count = 0
        while True:
            # 计算牛顿迭代公式
            next_x = x - (self.fn(x)/derivative(self.fn, x)) 
            err = abs(next_x - x)  # 计算误差
            if err < delta:  # 当误差小于设定的阈值时停止迭代
                break 
            else: 
                x = next_x  # 更新当前值
            count += 1  # 迭代次数加1
        return (next_x, count)  # 返回结果和迭代次数
